#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
SegmentMinCoo 轻量化样例精度校验脚本
"""

import logging
import sys
from pathlib import Path

import numpy as np

LOSS = 1e-4
MINIMUM = 1e-9


def verify_out(real_path: Path, golden_path: Path) -> bool:
    real = np.fromfile(real_path, dtype=np.float32)
    gold = np.fromfile(golden_path, dtype=np.float32)
    if real.size != gold.size:
        logging.error("out 大小不一致, real=%d, golden=%d", real.size, gold.size)
        return False
    diff = np.abs(real - gold)
    denom = np.maximum(np.abs(real), np.abs(gold))
    ok = np.logical_or(diff <= LOSS, diff / (denom + MINIMUM) <= LOSS)
    if not np.all(ok):
        logging.error("out 校验失败, 最大误差=%.6f", diff.max())
        return False
    logging.info("out tensor compare pass")
    return True


def verify_arg(real_path: Path, golden_path: Path) -> bool:
    real = np.fromfile(real_path, dtype=np.int32)
    gold = np.fromfile(golden_path, dtype=np.int32)
    if real.size != gold.size:
        logging.error("arg_out 大小不一致, real=%d, golden=%d", real.size, gold.size)
        return False
    if not np.array_equal(real, gold):
        logging.error("arg_out 校验失败")
        return False
    logging.info("arg_out tensor compare pass")
    return True


def main():
    if len(sys.argv) != 5:
        print("用法: python3 verify_result.py <real_out> <gold_out> <real_arg> <gold_arg>")
        sys.exit(1)
    logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s")
    real_out, gold_out, real_arg, gold_arg = map(Path, sys.argv[1:5])
    ok_out = verify_out(real_out, gold_out)
    ok_arg = verify_arg(real_arg, gold_arg)
    sys.exit(0 if (ok_out and ok_arg) else 1)


if __name__ == "__main__":
    main()
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""轻量化精度比对，同时校验 out 与 arg_out"""

import logging
import sys

import numpy as np

LOSS = 1e-3
MINIMUM = 1e-9


def verify_out(real_result, golden, dtype=np.float32):
    """比对浮点输出张量"""
    real = np.fromfile(real_result, dtype=dtype)
    gold = np.fromfile(golden, dtype=dtype)

    if real.size != gold.size:
        logging.error("size mismatch, real=%d, golden=%d", real.size, gold.size)
        return False

    diff = np.abs(real - gold)
    deno = np.maximum(np.abs(real), np.abs(gold))

    result_atol = diff <= LOSS
    result_rtol = diff / (deno + MINIMUM) <= LOSS

    if (not result_rtol.all()) and (not result_atol.all()):
        if (np.sum(result_rtol == 0) > real.size * LOSS and
                np.sum(result_atol == 0) > real.size * LOSS):
            logging.error("Compare failed!\n golden: %s\n real_result: %s\n", gold, real)
            return False

    logging.info("out tensor compare pass")
    return True


def verify_arg(real_result, golden, dtype=np.int32):
    """比对 arg_out（整型）"""
    real = np.fromfile(real_result, dtype=dtype)
    gold = np.fromfile(golden, dtype=dtype)

    if real.size != gold.size:
        logging.error("arg_out size mismatch, real=%d, golden=%d", real.size, gold.size)
        return False

    if not np.array_equal(real, gold):
        logging.error("arg_out compare failed!\n golden: %s\n real_result: %s\n", gold, real)
        return False

    logging.info("arg_out tensor compare pass")
    return True


if __name__ == "__main__":
    if len(sys.argv) < 5:
        print("用法: python3 verify_result.py <real_out> <gold_out> <real_arg> <gold_arg>")
        sys.exit(1)
    ok_out = verify_out(sys.argv[1], sys.argv[2])
    ok_arg = verify_arg(sys.argv[3], sys.argv[4])
    sys.exit(0 if (ok_out and ok_arg) else 1)
